iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
自我挑戰組

React 個人讀書會系列 第 27

Day 27 - 記憶元件:memo

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20231012/20103817npoWYEjNAn.jpg

什麼是 memo?

memo 函式用於建立一個在其父層重新渲染時不會重新渲染的元件,只要該元件在渲染之間 props 保持不變,但是當元件本身的狀態或是訂閱的 context 發生變化時,memo 元件仍然會重新渲染,因此,要特別提醒只有 props 會影響。

memo 元件

讓我們先將一般元件 Archive 放入 memo 函式裡面,將其包裝成 memo 元件。

// 一般元件
function Archive({ show }) {
  ...
}

// memo 元件
const Archive = memo(function Archive({ show }) {
  ...
});

接著來看一個例子,當我們點擊 button 按鈕更新 count 的狀態,App 元件會重新渲染,接著其子元件 Archive 也會重新渲染,但此時的 Archive 已經是一個 memo 元件,並且在渲染之間它的 props 始終保持 true,因此,即使父層 App 重新渲染,Archive 也不會重新渲染。

import { useState, memo } from "react";

function App() {
  const [count, setCount] = useState(0);

  return (
    <section>
      <h2>{count}</h2>
      <button onClick={() => setCount((count) => count + 1)}>++</button>
      <Archive show={true} />
    </section>
  );
}

const Archive = memo(function Archive({ show }) {
  console.log("Archive");

  return <h1>Archive</h1>;
});

但是當我們傳入的 props 是一個物件的時候,還是會導致重新渲染,這是為什麼呢?

原因是因為每當 App 重新渲染的時候,archiveOptions 這個物件會被重新建立,此時 archiveOptions 已經不是原本的那個物件,因此,archiveOptions 被視為一個新的 props 傳入,Archive 自然也就會重新渲染了,那該如何解決這個問題點呢?我們將在明天的文章裡介紹。

import { useState, memo } from "react";

function App() {
  const [count, setCount] = useState(0);

  const archiveOptions = {
    show: false,
    title: "Post archive"
  };

  return (
    <section>
      <h2>{count}</h2>
      <button onClick={() => setCount((count) => count + 1)}>++</button>
      <Archive archiveOptions={archiveOptions} />
    </section>
  );
}

const Archive = memo(function Archive({ show, title }) {
  console.log(show);

  return <h1>{title}</h1>;
});

memo 小總結

  1. 在 React 中,所有的值都會在每次渲染時重新建立(包括物件和函式)。
  2. 在 JavaScript 中,兩個看起來相同的物件或函式實際上是不同的({} !== {})。
  3. 如果物件或函式作為 props 傳遞,則子元件在每次重新渲染時始終將它們視為新的 props。
  4. 如果重新渲染之間的 props 不同,則 memo 將不起作用。
  5. 我們需要記憶住物件和函式,使它們在重新渲染之間保持穩定(memoized {} == memoized {})。

結語

透過 memo 函式,我們可以建立一個當父層重新渲染時不會重新渲染的元件,只要該元件的 props 在渲染之間保持不變,當父層會頻繁觸發重新渲染的時候,就可以將元件包裝成 memo 元件來避免不必要的重新渲染。


上一篇
Day 26 - 共享資料狀態:Context API
下一篇
Day 28 - 記憶值和函式:useMemo、useCallback
系列文
React 個人讀書會30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言